package com.plumecache.core.interceptor;

import com.alibaba.fastjson.JSON;
import com.plumecache.core.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.lang.reflect.Method;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;

@Slf4j
public class LogCacheInterceptor extends BaseCacheInterceptor {

    @Override
    public Integer getOrder() {
        return Integer.MAX_VALUE;
    }
    
    @Override
    public boolean preHandle(CacheService target, Method method, Object[] args, Map<String, Object> context) {
        Instant begin = Instant.now();
        context.put("instantBegin", begin);
        if (log.isDebugEnabled()) {
            log.debug("[LogCacheInterceptor]call instantBegin,method:{},args:{}"
                    , method.getDeclaringClass().getName() + "." + method.getName()
                    , JSON.toJSONString(args));
        }
        return true;
    }

    @Override
    public void postHandle(CacheService target, Method method, Object[] args, Map<String, Object> context, Object result) {
        Instant begin = (Instant) context.get("instantBegin");

        log.debug("[LogCacheInterceptor]call end,method:{},args:{},result:{},cost:{},speed:{}"
                , method.getDeclaringClass().getName() + "." + method.getName()
                , JSON.toJSONString(args)
                , JSON.toJSONString(result)
                , Duration.between(begin, Instant.now()).toMillis()
                , Duration.between(begin, Instant.now()).toMillis() > 200 ? "<<slow>>" : "<<fast>>");
    }

    @Override
    public void afterCompletion(CacheService target, Method method, Object[] args, Map<String, Object> context, Exception ex) {
        Instant begin = (Instant) context.get("instantBegin");

        log.error("[LogCacheInterceptor]call error,method:{},args:{},ex:{},cost:{},speed:{}"
                , method.getDeclaringClass().getName() + "." + method.getName()
                , JSON.toJSONString(args)
                , ExceptionUtils.getStackTrace(ex)
                , Duration.between(begin, Instant.now()).toMillis()
                , Duration.between(begin, Instant.now()).toMillis() > 200 ? "<<slow>>" : "<<fast>>");
    }

}
